/**
 * FileUploadHandler.java
 * Product:BaseLayer
 * Version:1.0
 * Copyright 2009 by DNE
 * All Rights Reserved.
 */
package com.site.util.common.fileupload;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import com.site.util.DateUtils;
import com.site.util.MessageUtils;
import com.site.util.StringUtils;
import com.site.util.Utilitys;
import com.site.util.base.businessbean.FileBean;
import com.site.util.exception.ApplicationException;
import com.site.util.exception.FileUploadException;


/**
 * 文件上传处理类
 * 通过该处理文件上传，并返回成功上传的文件。
 * @author  
 */
public class FileUploadHandle {
	
	public final static String NO="no";
	public final static String YES="yes";
	public final static String AUTO="auto";
	
	//允许上传的文件类型
	private String allowedTypes;
	
	//单个文件大小（单位：KB）
	private long maxSize;
	
	//源文件
	private File srcFile;
	
	//源文件名
	private String srcFileName;
	
	//目标文件名
	private String destFileName;
	
	//配制的上传文件目录，有可能是绝对路径，也有可能是相对路径
	private String uploadDir;
	
	//系统根据uploadDir解析绝对路径。
	private String realPathDir;
	
	//系统根据uploadDir解析相对路径。
	private String contextPath;
	
	//文件后缀
	private String suffix;
	
	private HttpServletRequest request;
	
	//设置文件名策略（NO{不改变文件名，如果有重复，覆盖老的} 
	//AUTO{如果有重复则重命名[不推荐使用]} 
	//YES{系统随机生成文件名}）
	private String needChangeFileName=NO;
	// 上传的文件
	private List<File> files = new ArrayList<File>();
	// 文件名称
	private List<String> filesName = new ArrayList<String>();
	
	
	public void setSrcFile(File srcFile) {
		this.srcFile = srcFile;
	}

	public void setSrcFileName(String srcFileName) {
		this.srcFileName = srcFileName;
	}

	public void setUploadDir(String uploadDir) {
		this.uploadDir = uploadDir;
	}

	public void setRequest(HttpServletRequest request) {
		this.request = request;
	}	
	
	public HttpServletRequest getRequest() {
		return request;
	}


	public void setNeedChangeFileName(String needChangeFileName) {
		this.needChangeFileName = needChangeFileName;
	}

	/**
	 * 开始处理上传文件
	 */
	public void upload() {
		if(srcFile==null){
			throw new FileUploadException("上传文件失败：找不到源文件srcFile＝"+srcFile);
		}
		if(StringUtils.isEmpty(srcFileName)){
			throw new FileUploadException("上传文件失败：找不到源文件名srcFileName＝"+srcFileName);
		}
		if(StringUtils.isEmpty(uploadDir)){
			throw new FileUploadException("上传文件失败：找不到上传目录路径uploadDir＝"+uploadDir);
		}
		
		//验证是否支持该文件上传
		suffix=srcFileName.substring(srcFileName.lastIndexOf(".")+1);
		if(!StringUtils.isEmpty(allowedTypes)){
			String[] array=allowedTypes.split(",");
			boolean allowed=false;
			for (int i = 0; i < array.length; i++) {
				if(suffix.equalsIgnoreCase(array[i].trim())){
					allowed=true;
				}
			}
			if(!allowed){
				String message=MessageUtils.getMessageString("SYS_MSG_00015", new String[]{suffix}, request);
				throw new FileUploadException(message);
			}
		}
		//验证文件大小是否超过设定的大小
		if(maxSize>0&&srcFile.length()>maxSize*1024){
			String message=MessageUtils.getMessageString("SYS_MSG_00014", new String[]{String.valueOf(maxSize)}, request);
			throw new FileUploadException(message);
		}
		
		try{
			this.parseUploadDir();
			this.initDestFileName();
			InputStream is = null;
			OutputStream ops = null;
			try {
				is = new FileInputStream(srcFile);
				File filePath = new File(realPathDir);
				if (!filePath.exists()) {
					filePath.mkdirs();
				}
				File destFile = new File(realPathDir, destFileName);
				//System.out.println("========realPathDir:"+realPathDir);
				//System.out.println("========destFileName:"+destFileName);
				ops = new FileOutputStream(destFile);
				byte[] b = new byte[1024];
				int length = 0;
				while ((length = is.read(b)) > 0) {
					ops.write(b, 0, length);
				}
			} catch (Exception ex) {
				ex.printStackTrace();
				String message=MessageUtils.getMessageString("SYS_MSG_00019", new String[]{String.valueOf(maxSize)}, request);
				throw new FileUploadException(message);
			} finally {
				if(is!=null)
					is.close();
				if(ops!=null)
					ops.close();
			}
		}catch(Exception e){
			String message=MessageUtils.getMessageString("SYS_MSG_00019", new String[]{String.valueOf(maxSize)}, request);
			throw new FileUploadException(message);
		}
	}
	
	/**
	 * 解析上传路径
	 * 判断是否以c:/，d:\\这种盘符开头的路径，这种路径系统认为是绝对路径，否则认为是应用根目录下路径
	 * 例如：uploadDir=d:/uploads/,则系统认为是绝对路径
	 * 		uploadDir＝/uploads/,则系统认为是应用下的/uploads/目录
	 */
	private void parseUploadDir() {
		if(System.getProperty("os.name").startsWith("Windows"))
		{
			if(uploadDir.length()>1&&':'==uploadDir.charAt(1)){
				realPathDir=uploadDir;
			}else{
				realPathDir=request.getSession().getServletContext().getRealPath(uploadDir);
				contextPath=request.getContextPath()+uploadDir;
			}
		}
		else
		{
			realPathDir=uploadDir;
		}
		
	}


	/**
	 * 目标文件名
	 */
	private void initDestFileName() {
		//不需更改文件名
		destFileName=srcFileName;
		//需要更改文件名
		if(YES.equals(needChangeFileName)){
			srcFileName.lastIndexOf(".");
			destFileName=generateRamdomName()+"."+suffix;
		}
		//如果当前目录下出现重名，则更改
		else if(AUTO.equals(needChangeFileName)){
			
			if(StringUtils.isEmpty(realPathDir)){
				throw new FileUploadException("SYS_MSG_00020");
			}
			
			File dir=new File(realPathDir);
			File[] fileList=dir.listFiles();
			if (fileList != null) {
				for (File file : fileList) {
					if(file.getName().equalsIgnoreCase(srcFileName)){
						destFileName=generateRamdomName()+"."+suffix;
						break;
					}
				}
			}
		}
	}
	
	/**
	 * 指定配制文件进行文件上传
	 * @return
	 */
	public List<FileBean> handleUploadFile() {
		List<FileBean> fileList=new ArrayList<FileBean>();
		try {
			for (int i = 0; i < files.size(); i++) {
				this.setNeedChangeFileName("auto");
				this.setSrcFile(files.get(i));
				this.setSrcFileName(filesName.get(i));
				this.upload();
				FileBean fileBean=new FileBean();
				fileBean.setNewName(this.getDestFileName());
				fileBean.setOldName(this.getSrcFileName());
				fileBean.setSize(this.getSrcFile().length());
				fileBean.setSuffix(this.getSuffix());
				String path=this.getContextPath()==null?this.getUploadDir():this.getContextPath();
				fileBean.setUrl(path+this.getDestFileName());
				fileList.add(fileBean);
			}
		}catch (Exception e) {
			e.printStackTrace();
			//将文件上传的异常传换成应用异常。
			throw new ApplicationException(e.getMessage(),e);
		}
		return fileList;
	}
	
	public String getAllowedTypes() {
		return allowedTypes;
	}

	public void setAllowedTypes(String allowedTypes) {
		this.allowedTypes = allowedTypes;
	}

	public long getMaxSize() {
		return maxSize;
	}

	public void setMaxSize(long maxSize) {
		this.maxSize = maxSize;
	}

	/**
	 * 生成随机文件名＝年年月日时分秒+四位随机数
	 * @return
	 */
	private String generateRamdomName(){
		long fourRandom=Utilitys.getRandom(4);
		String str=DateUtils.formatDate(new Date(), "yyyyMMddHHmmss");
		return str+fourRandom;
	}


	public String getDestFileName() {
		return destFileName;
	}


	public String getRealPathDir() {
		return realPathDir;
	}


	public String getContextPath() {
		return contextPath;
	}


	public String getSuffix() {
		return suffix;
	}

	public String getUploadDir() {
		return uploadDir;
	}

	public String getSrcFileName() {
		return srcFileName;
	}

	public File getSrcFile() {
		return srcFile;
	}

	public List<File> getFiles() {
		return files;
	}

	public void setFiles(List<File> files) {
		this.files = files;
	}

	public List<String> getFilesName() {
		return filesName;
	}

	public void setFilesName(List<String> filesName) {
		this.filesName = filesName;
	}
}
